"""
文件上传服务
"""

import os
import uuid
import aiofiles
from typing import List, Dict, Any, Optional
from fastapi import UploadFile, HTTPException
from PIL import Image
import shutil

from config import get_settings

settings = get_settings()

class UploadService:
    """文件上传服务类"""
    
    def __init__(self):
        self.upload_dir = settings.upload_dir
        self.max_file_size = settings.max_file_size
        self.allowed_extensions = settings.allowed_extensions
        
        # 确保上传目录存在
        os.makedirs(self.upload_dir, exist_ok=True)
        os.makedirs(os.path.join(self.upload_dir, "avatars"), exist_ok=True)
        os.makedirs(os.path.join(self.upload_dir, "files"), exist_ok=True)
    
    def validate_file_extension(self, file: UploadFile) -> bool:
        """验证文件扩展名"""
        if not file.filename:
            return False
        
        file_extension = file.filename.split('.')[-1].lower()
        return file_extension in self.allowed_extensions
    
    def validate_image_file(self, file: UploadFile) -> bool:
        """验证图片文件"""
        if not file.filename:
            return False
        
        file_extension = file.filename.split('.')[-1].lower()
        return file_extension in ['jpg', 'jpeg', 'png', 'gif']
    
    def validate_file_size(self, file: UploadFile, max_size: Optional[int] = None) -> bool:
        """验证文件大小"""
        if max_size is None:
            max_size = self.max_file_size
        
        # 获取文件大小
        file.file.seek(0, 2)  # 移动到文件末尾
        file_size = file.file.tell()
        file.file.seek(0)  # 重置文件指针
        
        return file_size <= max_size
    
    def generate_filename(self, original_filename: str) -> str:
        """生成唯一文件名"""
        file_extension = original_filename.split('.')[-1].lower()
        unique_filename = f"{uuid.uuid4().hex}.{file_extension}"
        return unique_filename
    
    async def upload_avatar(self, file: UploadFile, user_id: int) -> Dict[str, Any]:
        """上传用户头像"""
        try:
            # 生成文件名
            filename = self.generate_filename(file.filename)
            file_path = os.path.join(self.upload_dir, "avatars", filename)
            
            # 保存文件
            async with aiofiles.open(file_path, 'wb') as f:
                content = await file.read()
                await f.write(content)
            
            # 处理图片（压缩、调整尺寸）
            await self._process_avatar_image(file_path)
            
            # 构造文件URL
            file_url = f"/uploads/avatars/{filename}"
            
            return {
                "file_id": filename.split('.')[0],
                "filename": file.filename,
                "file_path": file_path,
                "file_url": file_url,
                "file_size": len(content),
                "upload_time": "now"
            }
            
        except Exception as e:
            # 清理已上传的文件
            if os.path.exists(file_path):
                os.remove(file_path)
            raise HTTPException(status_code=500, detail=f"文件上传失败: {str(e)}")
    
    async def upload_file(self, file: UploadFile, user_id: int) -> Dict[str, Any]:
        """上传通用文件"""
        try:
            # 生成文件名
            filename = self.generate_filename(file.filename)
            file_path = os.path.join(self.upload_dir, "files", filename)
            
            # 保存文件
            async with aiofiles.open(file_path, 'wb') as f:
                content = await file.read()
                await f.write(content)
            
            # 构造文件URL
            file_url = f"/uploads/files/{filename}"
            
            return {
                "file_id": filename.split('.')[0],
                "filename": file.filename,
                "file_path": file_path,
                "file_url": file_url,
                "file_size": len(content),
                "upload_time": "now"
            }
            
        except Exception as e:
            # 清理已上传的文件
            if os.path.exists(file_path):
                os.remove(file_path)
            raise HTTPException(status_code=500, detail=f"文件上传失败: {str(e)}")
    
    async def delete_file(self, file_id: str, user_id: int) -> None:
        """删除文件"""
        # 在实际应用中，这里应该从数据库中查找文件信息
        # 并验证用户权限
        
        # 查找文件
        avatar_pattern = os.path.join(self.upload_dir, "avatars", f"{file_id}.*")
        file_pattern = os.path.join(self.upload_dir, "files", f"{file_id}.*")
        
        import glob
        files_to_delete = glob.glob(avatar_pattern) + glob.glob(file_pattern)
        
        for file_path in files_to_delete:
            if os.path.exists(file_path):
                os.remove(file_path)
    
    async def _process_avatar_image(self, file_path: str) -> None:
        """处理头像图片"""
        try:
            with Image.open(file_path) as img:
                # 转换为RGB模式（如果是RGBA）
                if img.mode in ('RGBA', 'LA'):
                    background = Image.new('RGB', img.size, (255, 255, 255))
                    background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
                    img = background
                
                # 调整尺寸（最大200x200）
                img.thumbnail((200, 200), Image.Resampling.LANCZOS)
                
                # 保存处理后的图片
                img.save(file_path, 'JPEG', quality=85, optimize=True)
                
        except Exception as e:
            # 如果图片处理失败，保留原文件
            pass